home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 7 / Gekikoh Dennoh Club Vol. 7 (Japan).7z / Gekikoh Dennoh Club Vol. 7 (Japan) (Track 01).bin / games / otoko / source.lzh / FuncEnemy / lboss01.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-14  |  11.9 KB  |  475 lines

  1. /* 1面ボス */
  2. #include <xsp2lib.h>
  3.  
  4. #include "../otoko.h"
  5. #include "../player.h"
  6. #include "../enemy.h"
  7. #include "../eshot.h"
  8. #include "../effect.h"
  9. #include "../priority.h"
  10. #include "../entry.h"
  11. #include "../sound.h"
  12. #include "../psearch.h"
  13.  
  14.  
  15. #define SPEED_LASER        30
  16.  
  17. #define SPEED_1        3    /* 加速度 */
  18. #define SPEED_1N    28    /* 加速度を足す回数 */
  19.  
  20. #define SPEED_SHOT1    8    /* 1段階目扇型ショット速度 */
  21. #define SPEED_SHOT2    10    /* 2段階目伸びるショットの一番遅い弾の速度 */
  22. #define SPEED_SHOT3    12    /* 2段階目なぎ倒し弾の速度 */
  23.  
  24. #define HP_0    3000        /* 耐久力 */
  25. #define HP_1    2300        /* 耐久力がこれ以下になったら2段階目へ */
  26. #define HP_2    800        /* 耐久力がこれ以下になったら炸裂弾 */
  27. #define TIMER_1    1500        /* これ以上時間が経過したら2段階目へ */
  28. #define TIMER_2    3500        /* これ以上時間が経過したら撤退 */
  29.  
  30. #define SPEED_3        3    /* 3段階目(撤退)の加速度 */
  31. #define SPEED_3N    32    /* 3段階目の加速度を足す回数 */
  32.  
  33. #define SEQ_DEATH    6
  34.  
  35.  
  36.  
  37. enum {
  38.     MOVETO_INIT = 0,    /* 初期状態 */
  39.     MOVETO_C2L,        /* 中央から左に移動 */
  40.     MOVETO_L2C,
  41.     MOVETO_C2R,
  42.     MOVETO_R2C
  43. };
  44.  
  45. enum {
  46.     ATTACK_UPPER_CORE = 0,    /* 上のコアから攻撃(伸びる弾) */
  47.     ATTACK_LOWER_CORE    /* 下のコアから攻撃(ばらまき弾) */
  48. };
  49. static short EnemyMoveLBoss01 (ENEMY *);
  50. static void EnemyTiniLBoss01 (ENEMY *);
  51.  
  52.  
  53. void EnemyInitLBoss01 (ENEMY * p)
  54. {
  55.     p->vx = 0;
  56.     p->vy = 2 << 16;
  57.     p->hit_px = 54;
  58.     p->hit_py = 16;
  59.     p->hit_sx = 54;
  60.     p->hit_sy = 16;
  61.     p->hit_cx = 6;
  62.     p->timer = 0;
  63.     p->damage = 0;
  64.     p->flash = 0;
  65.     p->hp = HP_0;
  66.     p->pt = obj_lboss01 + 1;
  67.     p->core_pt = sp_core01;
  68.     p->seq = 0;
  69.     p->func_enemy_move = EnemyMoveLBoss01;
  70.     p->func_enemy_tini = EnemyTiniLBoss01;
  71.  
  72.     if (p->arg == 0)
  73.         p->work4 = PALET_LBOSS01 | PRIORITY_BOSS;
  74.     else
  75.         p->work4 = PALET_LBOSS01_1 | PRIORITY_BOSS;
  76.  
  77.     entry_counter_stop = !0;/* エントリーカウンター停止 */
  78. }
  79.  
  80.  
  81.  
  82. static short EnemyMoveLBoss01 (ENEMY * p)
  83. {
  84.     /* 速度を足して上位ワード(固定整数部)だけ取り出す */
  85.     p->x = (p->lx += p->vx) >> 16;
  86.     p->y = (p->ly += p->vy) >> 16;
  87.     p->timer++;
  88.  
  89.     switch (p->seq) {
  90.     case 0:
  91.         if (SHORT_LY > 64)
  92.             p->seq++;
  93.         break;
  94.     case 1:        /* 減速 */
  95.         p->vy -= 8192;
  96.         if (p->vy < 8192) {
  97.             p->seq++;
  98.             p->vy = 0;
  99.             p->m_work = MOVETO_INIT;    /* 移動方向 */
  100.             p->s_work = 0;
  101.         }
  102.         break;
  103.  
  104.         /* 第1形態 */
  105.     case 2:        /* 左右に移動しつつ扇状弾 */
  106.         /* まず移動処理 */
  107.         if (p->m_work == MOVETO_INIT) {
  108.             /* 初期状態なら */
  109.             if (p->x > player->x)
  110.                 p->m_work = MOVETO_C2L;    /* 移動方向 */
  111.             else
  112.                 p->m_work = MOVETO_C2R;    /* 移動方向 */
  113.             p->m_work2 = 0;
  114.         }
  115.         if (p->m_work2 == 0) {
  116.             /* 初回なら */
  117.             signed short dx, dy;
  118.             signed short dx_table[5] =
  119.             {0, 54 + 16, 128 + 16, 256 - 54 + 16, 128 + 16};
  120.             short m_work_table[5] =
  121.             {MOVETO_INIT, MOVETO_L2C, MOVETO_C2R, MOVETO_R2C, MOVETO_C2L};
  122.  
  123.             p->m_work2 = !0;
  124.             /* 順に左→中央→右→中央→左へ移動 */
  125.             dx = dx_table[p->m_work];
  126.             p->m_work = m_work_table[p->m_work];
  127.  
  128.             /* player->y は乱数の種として使用しています */
  129.             if (SHORT_LY < 80)
  130.                 dy = (((unsigned short) rndtable[(player->y) & 0xff]) / 4 + 32 + 16);
  131.             else
  132.                 dy = 64;
  133.             /* 移動方向を設定 */
  134.             SubEnemyMoveToInit (p, dx, dy, SPEED_1, SPEED_1N);
  135.         } else {
  136.             /* 設定値に従って移動 */
  137.             if (SubEnemyMoveTo (p) < 0)
  138.                 p->m_work2 = 0;    /* 移動方向再設定 */
  139.         }
  140.  
  141.         /* 次に攻撃処理 */
  142.         p->s_work++;
  143.         if (p->s_work == 1) {
  144.             p->s_angle = 16;
  145.             p->s_angle2 = 128 - 16;
  146.             p->s_work2 = 0;
  147.         }
  148.         if ((p->s_work > 6) && (p->s_work < 60)) {
  149.             p->s_work2++;
  150.             if (p->s_work2 > 3) {
  151.                 p->s_work2 = 0;
  152.                 EshotInit (ESHOT_NRG02, SHORT_LX, SHORT_LY, SPEED_SHOT1, p->s_angle, 3);
  153.                 EshotInit (ESHOT_NRG02, SHORT_LX, SHORT_LY, SPEED_SHOT1, p->s_angle2, 3);
  154.                 p->s_angle += 6;
  155.                 p->s_angle2 -= 6;
  156.                 SoundSetSE (SE_ESHOT);    /* 敵ショット音 */
  157.             }
  158.         }
  159.         if (p->s_work > 100)
  160.             p->s_work = 0;
  161.  
  162.         /* ある程度ダメージを受けた or 時間切れ */
  163.         if ((p->hp < HP_1) || (p->timer > TIMER_1)) {
  164.             /* カバー破棄 */
  165.             if (p->hp < HP_1)
  166.                 p->parts1 = EnemyInit (ENEMY_LBOSS01C, SHORT_LX, SHORT_LY, 0 + p->arg * 2, p);    /* カバーを分離 */
  167.             else
  168.                 p->parts1 = EnemyInit (ENEMY_LBOSS01C, SHORT_LX, SHORT_LY, 1 + p->arg * 2, p);    /* カバーを分離 */
  169.             if (!eshot_erase)
  170.                 eshot_erase = ESHOT_ERASE;    /* 弾消し */
  171.             p->pt++;
  172.             p->seq++;
  173.             p->m_work = 0;
  174.             p->m_work2 = 0;
  175.             p->hit_px = p->hit_sx = p->hit_py = p->hit_sy = 0;
  176.         }
  177.         break;
  178.     case 3:        /* アニメーション開始! */
  179.         p->m_work2++;
  180.         switch (p->m_work) {
  181.         case 0:
  182.             if (SubEnemyMoveTo (p) < 0)    /* 止まるまで待つ */
  183.                 p->m_work++;
  184.             break;
  185.         case 1:
  186.             if (p->m_work2 < 100)
  187.                 break;
  188.             if (p->pt < obj_lboss01 + 50) {
  189.                 p->pt++;
  190.             } else {
  191.                 p->seq++;
  192.                 p->cwork = ATTACK_UPPER_CORE;
  193.                 p->m_work = MOVETO_INIT;    /* 移動方向 */
  194.                 p->s_work = 0;
  195.                 p->s_work2 = 0;
  196.                 p->s_work3 = 0;    /* なぎ倒し弾用 */
  197.                 p->s_work4 = 0;    /* 炸裂弾用 */
  198.                 p->s_angle3 = 0;    /* なぎ倒し弾用 */
  199.                 p->hit_px = p->hit_sx = 70;
  200.                 p->hit_py = p->hit_sy = 16;
  201.             }
  202.             if ((p->pt == obj_lboss01 + 9) || (p->pt == obj_lboss01 + 30) || (p->pt == obj_lboss01 + 46))
  203.                 SoundSetSE (SE_LOCK_M);    /* 「がちゃん」という効果音を鳴らす */
  204.             break;
  205.         }
  206.         break;
  207.  
  208.  
  209.         /* 第2形態 */
  210.     case 4:
  211.         if (p->timer > TIMER_2) {
  212.             p->seq++;    /* 時間切れ */
  213.             p->m_work = 0;
  214.             break;
  215.         }
  216.         /* まず移動処理 */
  217.         if (p->m_work == MOVETO_INIT) {
  218.             /* 初期状態なら */
  219.             if (p->x > player->x)
  220.                 p->m_work = MOVETO_C2L;    /* 移動方向 */
  221.             else
  222.                 p->m_work = MOVETO_C2R;    /* 移動方向 */
  223.             p->m_work2 = 0;
  224.         }
  225.         if (p->m_work2 == 0) {
  226.             /* 初回なら */
  227.             signed short dx, dy;
  228.             signed short dx_table[5] =
  229.             {0, 32 + 16, 128 + 16, 256 - 32 + 16, 128 + 16};
  230.             short m_work_table[5] =
  231.             {MOVETO_INIT, MOVETO_L2C, MOVETO_C2R, MOVETO_R2C, MOVETO_C2L};
  232.  
  233.             p->m_work2 = !0;
  234.             /* 順に左→中央→右→中央→左へ移動 */
  235.             dx = dx_table[p->m_work];
  236.             p->m_work = m_work_table[p->m_work];
  237.  
  238.             /* player->y は乱数の種として使用しています */
  239.             if (SHORT_LY < 80)
  240.                 dy = (((unsigned short) rndtable[(player->y) & 0xff]) / 4 + 32 + 16);
  241.             else
  242.                 dy = 64;
  243.             /* 移動方向を設定 */
  244.             SubEnemyMoveToInit (p, dx, dy, SPEED_1, SPEED_1N);
  245.         } else {
  246.             /* 設定値に従って移動 */
  247.             if (SubEnemyMoveTo (p) < 0)
  248.                 p->m_work2 = 0;    /* 移動方向再設定 */
  249.         }
  250.  
  251.         /* 次に攻撃処理 */
  252.         if (p->cwork == ATTACK_UPPER_CORE) {
  253.             /* 上のコアから攻撃(伸びる弾) */
  254.             p->s_work++;
  255.             switch (p->s_work) {
  256.             case 1:
  257.                 p->s_angle = psearch (p->x, p->y);    /* 自機の方向をサーチ */
  258.                 if (p->x > player->x) {
  259.                     p->s_work2 = 0;
  260.                     p->s_angle -= 32;
  261.                 } else {
  262.                     p->s_work2 = !0;
  263.                     p->s_angle += 32;
  264.                 }
  265.                 break;
  266.             case 10 + 20 * 0:
  267.             case 10 + 20 * 1:
  268.             case 10 + 20 * 2:
  269.             case 10 + 20 * 3:
  270.             case 10 + 20 * 4:
  271.             case 10 + 20 * 5:
  272.             case 10 + 20 * 6:
  273.                 EshotInit (ESHOT_NRG03, SHORT_LX, SHORT_LY + 16, SPEED_SHOT2 + 3 * 0, p->s_angle, 3);
  274.                 EshotInit (ESHOT_NRG03, SHORT_LX, SHORT_LY + 16, SPEED_SHOT2 + 3 * 1, p->s_angle, 3);
  275.                 EshotInit (ESHOT_NRG03, SHORT_LX, SHORT_LY + 16, SPEED_SHOT2 + 3 * 2, p->s_angle, 3);
  276.                 EshotInit (ESHOT_NRG03, SHORT_LX, SHORT_LY + 16, SPEED_SHOT2 + 3 * 3, p->s_angle, 3);
  277.                 EshotInit (ESHOT_NRG03, SHORT_LX, SHORT_LY + 16, SPEED_SHOT2 + 3 * 4, p->s_angle, 3);
  278.                 EshotInit (ESHOT_NRG03, SHORT_LX, SHORT_LY + 16, SPEED_SHOT2 + 3 * 5, p->s_angle, 3);
  279.                 SoundSetSE (SE_LASER);    /* 敵ショット音 */
  280.                 if (p->s_work2 == 0)
  281.                     p->s_angle += 8;
  282.                 else
  283.                     p->s_angle -= 8;
  284.                 break;
  285.             case 10 + 20 * 9:
  286.                 p->cwork = ATTACK_LOWER_CORE;
  287.                 p->s_work = 0;
  288.                 p->s_work2 = 0;
  289.                 break;
  290.             default:
  291.                 break;
  292.             }
  293.         } else {
  294.             /* 下のコアから攻撃(扇状弾) */
  295.             p->s_work++;
  296.             if (p->s_work < 400) {
  297.                 if (p->s_work2++ > 1) {
  298.                     p->s_work2 = 0;
  299.                     EshotInit (ESHOT_NRG04, SHORT_LX, SHORT_LY, 7, rndtable[p->angle++] & 0xfc, 8);
  300.                     EshotInit (ESHOT_NRG04, SHORT_LX, SHORT_LY, 7, rndtable[p->angle++] & 0xfc, 8);
  301.                     SoundSetSE (SE_ESHOT);    /* 敵ショット音 */
  302.                 }
  303.             }
  304.             if (p->s_work == 480) {
  305.                 if (!eshot_erase)
  306.                     eshot_erase = ESHOT_ERASE;    /* 弾消し */
  307.             }
  308.             if (p->s_work > 500) {
  309.                 p->cwork = ATTACK_UPPER_CORE;
  310.                 p->s_work = 0;
  311.                 p->s_work2 = 0;
  312.             }
  313.         }
  314.         /* なぎ倒し弾 */
  315.         if (p->hp < HP_2) {
  316.             switch (p->s_work3++) {
  317.             case 0:
  318.                 EffectInit (EFFECT_EXPL, 0, p->x, p->y);
  319.                 SoundSetSE (SE_EXPL_M);    /* 中ボス爆発音 */
  320.                 break;
  321.             case 1:
  322.                 EshotInit (ESHOT_NRG02, SHORT_LX, SHORT_LY, SPEED_SHOT3, p->s_angle3, 0);
  323.                 EshotInit (ESHOT_NRG02, SHORT_LX, SHORT_LY, SPEED_SHOT3, p->s_angle3 + 128, 0);
  324.                 EshotInit (ESHOT_NRG02, SHORT_LX, SHORT_LY + 16, SPEED_SHOT3, p->s_angle3 + 64, 0);
  325.                 EshotInit (ESHOT_NRG02, SHORT_LX, SHORT_LY + 16, SPEED_SHOT3, p->s_angle3 + 192, 0);
  326.                 SoundSetSE (SE_ESHOT);
  327.                 p->s_angle3 += 16;
  328.                 break;
  329.             case 11:
  330.                 p->s_work3 = 1;
  331.                 break;
  332.             default:
  333.                 break;
  334.             }
  335.         }
  336.         /* ボスラッシュ時 */
  337. #define INTERVAL4_3    30
  338. #define SPEED_SHOT4_3    22
  339.         if (p->arg) {
  340.             if (p->s_work4++ > INTERVAL4_3) {
  341.                 short h;
  342.                 char a = 0;
  343.                 for (h = 0; h < 16; h++)
  344.                     EshotInit (ESHOT_NRG24N, SHORT_LX, SHORT_LY + 8, SPEED_SHOT4_3, a += 16, 3);
  345.                 SoundSetSE (SE_EBOMB_M);    /* 敵炸裂弾音 */
  346.                 p->s_work4 = 0;
  347.             }
  348.         }
  349.         break;
  350.  
  351.         /* 時間切れ撤退 */
  352.     case 5:
  353.         switch (p->m_work) {
  354.         case 0:
  355.             if (SubEnemyMoveTo (p) < 0) {    /* 止まるまで待つ */
  356.                 p->m_work++;
  357.                 SubEnemyMoveToInit (p, p->x, -128, SPEED_3, SPEED_3N);
  358.             }
  359.             break;
  360.         case 1:
  361.             if (SubEnemyMoveTo (p) < 0) {    /* 止まるまで待つ */
  362.                 entry_counter_stop = 0;    /* エントリーカウンター停止解除 */
  363.                 return (-1);    /* 消去 */
  364.             }
  365.             break;
  366.         }
  367.         break;
  368.  
  369.         /* 死んだ */
  370.     case SEQ_DEATH:
  371.         switch (p->m_work) {
  372.         case 0:
  373.             if (SubEnemyMoveToAbort (p) < 0) {    /* 止まるまで待つ */
  374.                 p->m_work++;
  375.                 p->m_work2 = 0;
  376.                 p->m_work3 = 0;
  377.                 /* 当たり判定を無くす */
  378.                 p->hit_px = p->hit_py = p->hit_sx = p->hit_sy = p->hit_cx = 0;
  379.                 if (!eshot_erase)
  380.                     eshot_erase = ESHOT_ERASE;    /* 弾消し */
  381.             }
  382.             break;
  383.         case 1:
  384.             if (p->m_work2++ > 3) {
  385.                 p->m_work2 = 0;
  386.                 p->m_work3++;
  387.                 if (p->m_work3 < 15) {
  388.                     signed short x, y;
  389.                     x = rndtable[(p->timer) & 0xff ^ 0x55] - 128;
  390.                     y = rndtable[(p->timer) & 0xff ^ 0xaa] - 128;
  391.                     /* p->timer は乱数の種として使用しています */
  392.                     EffectInit (EFFECT_EXPL, 0, x / 2 + p->x, y / 4 + p->y + 16);
  393.                     SoundSetSE (SE_EXPL_M);    /* 中ボス爆発音 */
  394.                 }
  395.                 if (p->m_work3 > 20) {
  396.                     short h;
  397.                     for (h = 0; h < 6; h++) {
  398.                         EffectInit (EFFECT_EXPL, 0,
  399.                                 (signed short) ((rndtable[h] - 128) / 2) + p->x,
  400.                                 (signed short) ((rndtable[h + 1] - 128) / 4) + p->y + 16);
  401.                     }
  402.                     SoundSetSE (SE_EXPL_L);    /* ボスキャラ爆発音 */
  403.                     if (p->core_info == (PALET_CORE_RED | PRIORITY_BOSS_CORE))
  404.                         EffectInit (EFFECT_POINTS_RED, POINTS_10000, p->x, p->y);
  405.                     else
  406.                         EffectInit (EFFECT_POINTS_BLUE, POINTS_5000, p->x, p->y);
  407.                     EffectInit (EFFECT_HAHEN, 0, p->x, p->y);
  408.  
  409.                     entry_counter_stop = 0;    /* エントリーカウンター停止解除 */
  410.                     return (-1);    /* 消去 */
  411.                 }
  412.             }
  413.             break;
  414.         }
  415.     default:
  416.         break;
  417.     }
  418.  
  419.     /* 画面外に出たら消去 */
  420.     if (SHORT_LY > 256 + 32)
  421.         return (-1);    /* 消去 */
  422.  
  423.  
  424.     /* 自機ショットに当たった時の処理 */
  425.     if (p->damage) {
  426.         if (p->damage_core) {
  427.             SoundSetSE (SE_CORE_DAMAGE);
  428.             p->info = PALET_RED | PRIORITY_BOSS;
  429.             p->damage_core = 0;
  430.         } else {
  431.             SoundSetSE (SE_DAMAGE);
  432.             p->info = PALET_DAMAGE | PRIORITY_BOSS;
  433.         }
  434.         if ((p->hp -= p->damage) <= 0) {
  435.             /* 死んだ */
  436.             p->seq = SEQ_DEATH;
  437.             p->m_work = 0;
  438.         }
  439.         p->damage = 0;
  440.         p->flash = TIMER_FLASH_DAMAGE;
  441.     } else {
  442.         if ((p->flash++ > TIMER_FLASH_RED) && (p->hp < 300)) {
  443.             p->info = PALET_RED | PRIORITY_BOSS;
  444.             if (p->flash > TIMER_FLASH_NORMAL)
  445.                 p->flash = 0;
  446.         } else {
  447.             p->info = p->work4;
  448.         }
  449.     }
  450.  
  451.     xobj_set_st (p);
  452.  
  453.     /* コアの表示 */
  454.     p->core_x = p->x - 8;    /* コアの中心は (-8,-8) ドットずれる */
  455.     p->core_y = p->y - 8;
  456.     if (p->seq != SEQ_DEATH) {    /* 死んだらコア状態は変化させない */
  457.         if (player->y < p->y + 96)    /* 自機との座標の差が小さければ赤 */
  458.             p->core_info = PALET_CORE_RED | PRIORITY_BOSS_CORE;
  459.         else
  460.             p->core_info = PALET_CORE_BLUE | PRIORITY_BOSS_CORE;
  461.     }
  462.     xsp_set_st (&(p->core_x));
  463.     /* コア2つ目 */
  464.     p->core_x = p->x - 8;    /* コアの中心は (-8,+8) ドットずれる */
  465.     p->core_y = p->y + 8;
  466.     xsp_set_st (&(p->core_x));
  467.  
  468.     return (0);
  469. }
  470.  
  471.  
  472. static void EnemyTiniLBoss01 (ENEMY * p)
  473. {
  474. }
  475.